package com.smart.translator.util;

import android.content.Context;
import android.media.AudioFormat;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;

import org.json.JSONException;
import org.json.JSONObject;
import org.vosk.Model;
import org.vosk.Recognizer;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

/**
 * Vosk离线语音识别工具类
 * 支持中文语音识别，自动加载模型
 */
public class VoskSpeechRecognizer {
    private static final String TAG = "VoskSpeechRecognizer";
    
    // 音频配置
    private static final int SAMPLE_RATE = 16000;
    private static final int CHANNEL_CONFIG = AudioFormat.CHANNEL_IN_MONO;
    private static final int AUDIO_FORMAT = AudioFormat.ENCODING_PCM_16BIT;
    private static final int BUFFER_SIZE = AudioRecord.getMinBufferSize(SAMPLE_RATE, CHANNEL_CONFIG, AUDIO_FORMAT);
    
    // Silero VAD固定帧大小（1024样本 = 2048字节 @ 16kHz）
    private static final int SILERO_FRAME_SIZE = 1024; // 样本数
    private static final int SILERO_FRAME_BYTES = SILERO_FRAME_SIZE * 2; // 字节数（每个样本2字节）
    
    // 音频输入源
    public static final int AUDIO_SOURCE_MIC = MediaRecorder.AudioSource.MIC; // 手机麦克风
    public static final int AUDIO_SOURCE_DEFAULT = MediaRecorder.AudioSource.DEFAULT; // 默认音频源（通常是蓝牙耳机）
    
    private Context context;
    private Model model;
    private Recognizer recognizer;
    private AudioRecord audioRecord;
    private ExecutorService executorService;
    private Handler mainHandler;
    
    private boolean isRecording = false;
    private boolean isModelLoaded = false;
    private int audioSource = AUDIO_SOURCE_MIC; // 默认使用手机麦克风
    
    // VAD检测器
    private VadDetector vadDetector;
    private boolean isVadEnabled = false;
    
    // VAD音频缓冲区（用于累积数据到Silero VAD要求的帧大小）
    private byte[] vadAudioBuffer = null;
    private int vadBufferPosition = 0;
    
    // VAD回调接口
    public interface VadCallback {
        void onVadSpeechStart();
        void onVadSpeechEnd();
        void onVadVoiceActivity(boolean isSpeech);
    }
    
    private VadCallback vadCallback;
    
    // 语音识别回调接口
    public interface SpeechRecognitionListener {
        void onResult(String result);
        void onPartialResult(String partialResult);
        void onError(String error);
        void onModelLoaded();
        void onModelLoadError(String error);
    }
    
    private SpeechRecognitionListener listener;
    
    // 1. 添加成员变量
    private android.content.BroadcastReceiver vadControlReceiver;
    
    public VoskSpeechRecognizer(Context context) {
        this.context = context;
        this.executorService = Executors.newSingleThreadExecutor();
        this.mainHandler = new Handler(Looper.getMainLooper());
        
        // 初始化VAD检测器
        initVadDetector();
        // 注册VAD控制广播
        vadControlReceiver = new android.content.BroadcastReceiver() {
            @Override
            public void onReceive(Context ctx, android.content.Intent intent) {
                String action = intent.getAction();
                if (com.smart.translator.ble.AudioProcessor.ACTION_PAUSE_VOSK_VAD.equals(action)) {
                    pauseVadDetection();
                    Log.d(TAG, "收到广播，暂停Vosk VAD检测");
                } else if (com.smart.translator.ble.AudioProcessor.ACTION_RESUME_VOSK_VAD.equals(action)) {
                    resumeVadDetection();
                    Log.d(TAG, "收到广播，恢复Vosk VAD检测");
                }
            }
        };
        android.content.IntentFilter filter = new android.content.IntentFilter();
        filter.addAction(com.smart.translator.ble.AudioProcessor.ACTION_PAUSE_VOSK_VAD);
        filter.addAction(com.smart.translator.ble.AudioProcessor.ACTION_RESUME_VOSK_VAD);
        androidx.localbroadcastmanager.content.LocalBroadcastManager.getInstance(context)
            .registerReceiver(vadControlReceiver, filter);
    }
    
    /**
     * 初始化VAD检测器
     */
    private void initVadDetector() {
        try {
            // 设置VAD类型为Silero VAD
            VadDetector.setVadType(VadDetector.VadType.SILERO);
            
            vadDetector = new VadDetector(context);
            
            // 设置VAD回调
            vadDetector.setCallback(new VadDetector.VadCallback() {
                @Override
                public void onSpeechStart() {
                    Log.d(TAG, "🎤 Vosk VAD检测到语音开始");
                    if (vadCallback != null) {
                        mainHandler.post(() -> vadCallback.onVadSpeechStart());
                    }
                }
                
                @Override
                public void onSpeechEnd() {
                    Log.d(TAG, "🔇 Vosk VAD检测到语音结束");
                    if (vadCallback != null) {
                        mainHandler.post(() -> vadCallback.onVadSpeechEnd());
                    }
                }
                
                @Override
                public void onVoiceActivity(boolean isSpeech) {
                    if (vadCallback != null) {
                        mainHandler.post(() -> vadCallback.onVadVoiceActivity(isSpeech));
                    }
                }
                
                @Override
                public void onVadError(String error) {
                    Log.e(TAG, "Vosk VAD错误: " + error);
                }
            });
            
            // 初始化VAD检测器（16kHz采样率，与Vosk一致）
            vadDetector.initialize(SAMPLE_RATE, SILERO_FRAME_SIZE); // 1024帧大小 @ 16kHz，匹配Silero VAD要求
            
            // 初始化VAD音频缓冲区
            vadAudioBuffer = new byte[SILERO_FRAME_BYTES];
            vadBufferPosition = 0;
            
            isVadEnabled = true;
            
            Log.d(TAG, "✅ Vosk VAD检测器初始化成功");
            
        } catch (Exception e) {
            Log.e(TAG, "❌ Vosk VAD检测器初始化失败", e);
            isVadEnabled = false;
        }
    }
    
    /**
     * 设置VAD回调
     */
    public void setVadCallback(VadCallback callback) {
        this.vadCallback = callback;
    }
    
    /**
     * 设置语音识别回调
     */
    public void setSpeechRecognitionListener(SpeechRecognitionListener listener) {
        this.listener = listener;
    }
    
    /**
     * 加载语音识别模型
     * 支持从assets目录的zip文件或文件夹加载
     */
    public void loadModel(String modelPath) {
        executorService.execute(() -> {
            try {
                Log.d(TAG, "开始加载Vosk模型: " + modelPath);
                
                String internalModelPath;
                
                // 检查是否是zip文件
                if (modelPath.endsWith(".zip")) {
                    try {
                        internalModelPath = extractModelFromZip(modelPath);
                    } catch (IOException e) {
                        Log.e(TAG, "zip文件解压失败，尝试作为文件夹处理: " + e.getMessage());
                        // 如果zip解压失败，尝试作为文件夹处理
                        String folderPath = modelPath.substring(0, modelPath.lastIndexOf('.'));
                        internalModelPath = copyModelToInternalStorage(folderPath);
                    }
                } else {
                    // 从assets目录加载模型文件夹
                    internalModelPath = copyModelToInternalStorage(modelPath);
                }
                
                if (internalModelPath == null) {
                    throw new IOException("无法加载模型文件");
                }
                
                model = new Model(internalModelPath);
                
                // 创建识别器
                recognizer = new Recognizer(model, SAMPLE_RATE);
                
                isModelLoaded = true;
                Log.d(TAG, "Vosk模型加载成功");
                
                if (listener != null) {
                    mainHandler.post(() -> listener.onModelLoaded());
                }
                
            } catch (IOException e) {
                Log.e(TAG, "加载Vosk模型失败", e);
                isModelLoaded = false;
                if (listener != null) {
                    mainHandler.post(() -> listener.onModelLoadError("模型加载失败: " + e.getMessage()));
                }
            }
        });
    }
    
    /**
     * 将assets中的模型文件复制到内部存储
     */
    private String copyModelToInternalStorage(String modelPath) throws IOException {
        // 创建内部存储目录
        File modelDir = new File(context.getFilesDir(), "vosk_models");
        if (!modelDir.exists()) {
            modelDir.mkdirs();
        }
        
        File targetDir = new File(modelDir, modelPath);
        if (targetDir.exists()) {
            Log.d(TAG, "模型文件已存在: " + targetDir.getAbsolutePath());
            // 检查现有文件是否完整
            if (isModelComplete(targetDir)) {
                // 返回实际的模型目录路径
                File actualModelDir = findActualModelDirectory(targetDir);
                if (actualModelDir != null) {
                    Log.d(TAG, "返回实际模型目录路径: " + actualModelDir.getAbsolutePath());
                    return actualModelDir.getAbsolutePath();
                } else {
                    Log.e(TAG, "无法找到实际的模型目录");
                    throw new IOException("无法找到实际的模型目录");
                }
            } else {
                Log.w(TAG, "现有模型文件不完整，重新复制");
            }
        }
        
        // 复制模型文件
        if (modelPath.endsWith(".zip")) {
            return extractModelFromZip(modelPath);
        } else {
            return copyModelFolder(modelPath);
        }
    }
    
    /**
     * 复制assets中的目录
     */
    private void copyAssetDirectory(String assetPath, File targetDir) throws IOException {
        targetDir.mkdirs();
        String[] assets = context.getAssets().list(assetPath);
        if (assets != null) {
            Log.d(TAG, "复制目录: " + assetPath + " (包含 " + assets.length + " 个项目)");
            for (String asset : assets) {
                String newAssetPath = assetPath + "/" + asset;
                File newTargetFile = new File(targetDir, asset);
                
                // 检查是否是目录
                String[] subAssets = context.getAssets().list(newAssetPath);
                if (subAssets != null && subAssets.length > 0) {
                    // 这是一个目录，递归复制
                    copyAssetDirectory(newAssetPath, newTargetFile);
                } else {
                    // 这是一个文件，直接复制
                    copyAssetFile(newAssetPath, newTargetFile);
                }
            }
        }
    }
    
    /**
     * 复制assets中的文件
     */
    private void copyAssetFile(String assetPath, File targetFile) throws IOException {
        InputStream inputStream = null;
        FileOutputStream outputStream = null;
        
        try {
            Log.d(TAG, "复制文件: " + assetPath + " -> " + targetFile.getAbsolutePath());
            inputStream = context.getAssets().open(assetPath);
            outputStream = new FileOutputStream(targetFile);
            
            byte[] buffer = new byte[8192]; // 使用更大的缓冲区
            int length;
            long totalBytes = 0;
            while ((length = inputStream.read(buffer)) > 0) {
                outputStream.write(buffer, 0, length);
                totalBytes += length;
            }
            
            Log.d(TAG, "文件复制完成: " + assetPath + " (" + totalBytes + " 字节)");
            
        } catch (IOException e) {
            Log.e(TAG, "复制文件失败: " + assetPath, e);
            throw e;
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    Log.e(TAG, "关闭输入流失败", e);
                }
            }
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    Log.e(TAG, "关闭输出流失败", e);
                }
            }
        }
    }
    
    /**
     * 检查zip文件内容
     */
    private void checkZipContents(String zipPath) {
        try {
            InputStream zipStream = context.getAssets().open(zipPath);
            ZipInputStream zis = new ZipInputStream(zipStream);
            
            Log.d(TAG, "检查zip文件内容: " + zipPath);
            
            ZipEntry entry;
            int fileCount = 0;
            int dirCount = 0;
            long totalSize = 0;
            
            while ((entry = zis.getNextEntry()) != null) {
                if (entry.isDirectory()) {
                    dirCount++;
                    Log.d(TAG, "目录: " + entry.getName());
                } else {
                    fileCount++;
                    totalSize += entry.getSize();
                    Log.d(TAG, "文件: " + entry.getName() + " (" + entry.getSize() + " 字节)");
                }
                zis.closeEntry();
            }
            
            zis.close();
            zipStream.close();
            
            Log.d(TAG, "zip文件统计: " + fileCount + " 个文件, " + dirCount + " 个目录, 总大小: " + totalSize + " 字节");
            
        } catch (IOException e) {
            Log.e(TAG, "检查zip文件内容失败", e);
        }
    }
    
    /**
     * 从zip文件解压模型
     */
    private String extractModelFromZip(String zipPath) throws IOException {
        // 先检查zip文件内容
        checkZipContents(zipPath);
        
        // 创建内部存储目录
        File modelDir = new File(context.getFilesDir(), "vosk_models");
        if (!modelDir.exists()) {
            modelDir.mkdirs();
        }
        
        // 提取模型名称（去掉.zip后缀）
        String modelName = zipPath.substring(0, zipPath.lastIndexOf('.'));
        File targetDir = new File(modelDir, modelName);
        
        if (targetDir.exists()) {
            Log.d(TAG, "模型文件已存在: " + targetDir.getAbsolutePath());
            // 检查现有文件是否完整
            if (isModelComplete(targetDir)) {
                // 返回实际的模型目录路径
                File actualModelDir = findActualModelDirectory(targetDir);
                if (actualModelDir != null) {
                    Log.d(TAG, "返回实际模型目录路径: " + actualModelDir.getAbsolutePath());
                    return actualModelDir.getAbsolutePath();
                } else {
                    Log.e(TAG, "无法找到实际的模型目录");
                    throw new IOException("无法找到实际的模型目录");
                }
            } else {
                Log.d(TAG, "现有模型文件不完整，重新解压");
                deleteDirectory(targetDir);
            }
        }
        
        // 解压zip文件
        try {
            InputStream zipStream = context.getAssets().open(zipPath);
            ZipInputStream zis = new ZipInputStream(zipStream);
            
            Log.d(TAG, "开始解压zip文件: " + zipPath);
            
            // 记录解压的文件列表
            java.util.List<String> extractedFiles = new java.util.ArrayList<>();
            
            ZipEntry entry;
            while ((entry = zis.getNextEntry()) != null) {
                String entryName = entry.getName();
                
                // 跳过根目录条目（如果存在）
                if (entryName.equals(modelName + "/") || entryName.equals(modelName + "\\")) {
                    Log.d(TAG, "跳过根目录条目: " + entryName);
                    zis.closeEntry();
                    continue;
                }
                
                // 移除根目录前缀（如果存在）
                String relativePath = entryName;
                if (entryName.startsWith(modelName + "/")) {
                    relativePath = entryName.substring(modelName.length() + 1);
                }
                
                File targetFile = new File(targetDir, relativePath);
                
                Log.d(TAG, "解压: " + entryName + " -> " + targetFile.getAbsolutePath());
                extractedFiles.add(relativePath);
                
                if (entry.isDirectory()) {
                    targetFile.mkdirs();
                    Log.d(TAG, "创建目录: " + relativePath);
                } else {
                    // 确保父目录存在
                    File parentDir = targetFile.getParentFile();
                    if (parentDir != null && !parentDir.exists()) {
                        parentDir.mkdirs();
                        Log.d(TAG, "创建父目录: " + parentDir.getAbsolutePath());
                    }
                    
                    // 解压文件
                    FileOutputStream fos = new FileOutputStream(targetFile);
                    byte[] buffer = new byte[8192];
                    int length;
                    long totalBytes = 0;
                    while ((length = zis.read(buffer)) > 0) {
                        fos.write(buffer, 0, length);
                        totalBytes += length;
                    }
                    fos.close();
                    
                    Log.d(TAG, "文件解压完成: " + relativePath + " (" + totalBytes + " 字节)");
                }
                
                zis.closeEntry();
            }
            
            zis.close();
            zipStream.close();
            
            // 输出解压的文件列表
            Log.d(TAG, "解压完成，共解压 " + extractedFiles.size() + " 个文件:");
            for (String file : extractedFiles) {
                Log.d(TAG, "  - " + file);
            }
            
            // 验证解压结果
            if (isModelComplete(targetDir)) {
                // 返回实际的模型目录路径
                File actualModelDir = findActualModelDirectory(targetDir);
                if (actualModelDir != null) {
                    Log.d(TAG, "模型文件解压完成: " + actualModelDir.getAbsolutePath());
                    return actualModelDir.getAbsolutePath();
                } else {
                    Log.e(TAG, "无法找到实际的模型目录");
                    throw new IOException("无法找到实际的模型目录");
                }
            } else {
                Log.e(TAG, "模型文件解压不完整");
                throw new IOException("模型文件解压不完整");
            }
            
        } catch (IOException e) {
            Log.e(TAG, "解压模型文件失败", e);
            throw e;
        }
    }
    
    /**
     * 复制模型文件夹
     */
    private String copyModelFolder(String modelPath) throws IOException {
        File modelDir = new File(context.getFilesDir(), "vosk_models");
        File targetDir = new File(modelDir, modelPath);
        
        // 复制assets中的模型文件
        try {
            String[] assets = context.getAssets().list(modelPath);
            if (assets == null || assets.length == 0) {
                Log.e(TAG, "模型路径不存在: " + modelPath);
                throw new IOException("模型路径不存在: " + modelPath);
            }
            
            Log.d(TAG, "开始复制模型文件夹，找到 " + assets.length + " 个项目");
            
            // 创建目标目录
            targetDir.mkdirs();
            
            // 复制所有文件
            for (String asset : assets) {
                String assetPath = modelPath + "/" + asset;
                File targetFile = new File(targetDir, asset);
                
                Log.d(TAG, "复制: " + assetPath + " -> " + targetFile.getAbsolutePath());
                
                // 检查是否是目录
                String[] subAssets = context.getAssets().list(assetPath);
                if (subAssets != null && subAssets.length > 0) {
                    // 这是一个目录，递归复制
                    copyAssetDirectory(assetPath, targetFile);
                } else {
                    // 这是一个文件，直接复制
                    copyAssetFile(assetPath, targetFile);
                }
            }
            
            // 验证复制结果
            if (isModelComplete(targetDir)) {
                // 返回实际的模型目录路径
                File actualModelDir = findActualModelDirectory(targetDir);
                if (actualModelDir != null) {
                    Log.d(TAG, "模型文件夹复制完成: " + actualModelDir.getAbsolutePath());
                    return actualModelDir.getAbsolutePath();
                } else {
                    Log.e(TAG, "无法找到实际的模型目录");
                    throw new IOException("无法找到实际的模型目录");
                }
            } else {
                Log.e(TAG, "模型文件夹复制不完整");
                throw new IOException("模型文件夹复制不完整");
            }
            
        } catch (IOException e) {
            Log.e(TAG, "复制模型文件夹失败", e);
            throw e;
        }
    }

    /**
     * 复制模型文件
     */
    
    /**
     * 列出目录结构（用于调试）
     */
    private void listDirectoryStructure(File dir, String prefix) {
        if (!dir.exists()) {
            Log.d(TAG, prefix + "目录不存在: " + dir.getName());
            return;
        }
        
        File[] files = dir.listFiles();
        if (files == null) {
            Log.d(TAG, prefix + "无法列出目录内容: " + dir.getName());
            return;
        }
        
        Log.d(TAG, prefix + "目录: " + dir.getName() + " (包含 " + files.length + " 个项目)");
        for (File file : files) {
            if (file.isDirectory()) {
                listDirectoryStructure(file, prefix + "  ");
            } else {
                Log.d(TAG, prefix + "  文件: " + file.getName() + " (" + file.length() + " 字节)");
            }
        }
    }
    
    /**
     * 检查模型文件是否完整
     */
    private boolean isModelComplete(File modelDir) {
        Log.d(TAG, "检查模型完整性: " + modelDir.getAbsolutePath());
        
        // 列出完整的目录结构
        listDirectoryStructure(modelDir, "");
        
        // 查找实际的模型目录（处理嵌套目录结构）
        File actualModelDir = findActualModelDirectory(modelDir);
        if (actualModelDir == null) {
            Log.e(TAG, "无法找到实际的模型目录");
            return false;
        }
        
        Log.d(TAG, "找到实际模型目录: " + actualModelDir.getAbsolutePath());
        
        // 检查关键文件和目录 - 不同版本的Vosk模型可能有不同的结构
        String[] requiredItems = {"am", "conf", "graph"};
        boolean hasRequiredItems = true;
        
        for (String item : requiredItems) {
            File file = new File(actualModelDir, item);
            if (!file.exists()) {
                Log.e(TAG, "缺少必要文件/目录: " + item);
                hasRequiredItems = false;
            } else {
                Log.d(TAG, "找到: " + item + " (" + (file.isDirectory() ? "目录" : "文件") + ")");
            }
        }
        
        // 检查am目录中的final.mdl文件
        File finalMdl = new File(actualModelDir, "am/final.mdl");
        if (!finalMdl.exists()) {
            Log.e(TAG, "缺少关键文件: am/final.mdl");
            hasRequiredItems = false;
        } else {
            Log.d(TAG, "找到: am/final.mdl (" + finalMdl.length() + " 字节)");
        }
        
        // 检查conf目录中的配置文件
        File confFile = new File(actualModelDir, "conf/mfcc.conf");
        if (!confFile.exists()) {
            Log.e(TAG, "缺少配置文件: conf/mfcc.conf");
            hasRequiredItems = false;
        } else {
            Log.d(TAG, "找到: conf/mfcc.conf (" + confFile.length() + " 字节)");
        }
        
        // 检查graph目录中的文件
        File graphDir = new File(actualModelDir, "graph");
        if (graphDir.exists() && graphDir.isDirectory()) {
            File[] graphFiles = graphDir.listFiles();
            if (graphFiles != null && graphFiles.length > 0) {
                Log.d(TAG, "graph目录包含 " + graphFiles.length + " 个文件");
                for (File file : graphFiles) {
                    Log.d(TAG, "  - " + file.getName() + " (" + file.length() + " 字节)");
                }
            } else {
                Log.e(TAG, "graph目录为空");
                hasRequiredItems = false;
            }
        }
        
        // 检查是否有其他重要文件
        File featuresFile = new File(actualModelDir, "features.txt");
        if (featuresFile.exists()) {
            Log.d(TAG, "找到: features.txt (" + featuresFile.length() + " 字节)");
        }
        
        File finalRawFile = new File(actualModelDir, "final.raw");
        if (finalRawFile.exists()) {
            Log.d(TAG, "找到: final.raw (" + finalRawFile.length() + " 字节)");
        }
        
        if (hasRequiredItems) {
            Log.d(TAG, "模型完整性检查通过");
            return true;
        } else {
            Log.e(TAG, "模型完整性检查失败");
            return false;
        }
    }
    
    /**
     * 查找实际的模型目录（处理嵌套目录结构）
     */
    private File findActualModelDirectory(File modelDir) {
        // 首先检查当前目录是否包含模型文件
        if (isDirectoryContainsModelFiles(modelDir)) {
            return modelDir;
        }
        
        // 如果当前目录不包含模型文件，查找子目录
        File[] subDirs = modelDir.listFiles(File::isDirectory);
        if (subDirs != null) {
            for (File subDir : subDirs) {
                if (isDirectoryContainsModelFiles(subDir)) {
                    return subDir;
                }
                
                // 递归查找更深层的目录
                File deeperDir = findActualModelDirectory(subDir);
                if (deeperDir != null) {
                    return deeperDir;
                }
            }
        }
        
        return null;
    }
    
    /**
     * 检查目录是否包含模型文件
     */
    private boolean isDirectoryContainsModelFiles(File dir) {
        // 检查是否存在am、conf、graph目录
        File amDir = new File(dir, "am");
        File confDir = new File(dir, "conf");
        File graphDir = new File(dir, "graph");
        
        boolean hasAm = amDir.exists() && amDir.isDirectory();
        boolean hasConf = confDir.exists() && confDir.isDirectory();
        boolean hasGraph = graphDir.exists() && graphDir.isDirectory();
        
        // 检查关键文件
        File finalMdl = new File(dir, "am/final.mdl");
        File mfccConf = new File(dir, "conf/mfcc.conf");
        
        boolean hasFinalMdl = finalMdl.exists() && finalMdl.isFile();
        boolean hasMfccConf = mfccConf.exists() && mfccConf.isFile();
        
        return hasAm && hasConf && hasGraph && hasFinalMdl && hasMfccConf;
    }
    
    /**
     * 删除目录及其内容
     */
    private void deleteDirectory(File dir) {
        if (dir.exists()) {
            File[] files = dir.listFiles();
            if (files != null) {
                for (File file : files) {
                    if (file.isDirectory()) {
                        deleteDirectory(file);
                    } else {
                        file.delete();
                    }
                }
            }
            dir.delete();
        }
    }
    
    /**
     * 开始语音识别
     */
    public void startRecognition() {
        if (!isModelLoaded) {
            if (listener != null) {
                listener.onError("模型未加载，请先加载模型");
            }
            return;
        }
        
        if (isRecording) {
            Log.w(TAG, "语音识别已在运行中");
            return;
        }
        
        executorService.execute(() -> {
            try {
                // 确保之前的AudioRecord已清理
                if (audioRecord != null) {
                    try {
                        audioRecord.release();
                    } catch (Exception e) {
                        Log.e(TAG, "清理之前的AudioRecord时发生错误", e);
                    }
                    audioRecord = null;
                }
                
                // 初始化音频录制
                audioRecord = new AudioRecord(
                    audioSource, // 使用指定的音频源
                    SAMPLE_RATE,
                    CHANNEL_CONFIG,
                    AUDIO_FORMAT,
                    BUFFER_SIZE
                );
                
                if (audioRecord.getState() != AudioRecord.STATE_INITIALIZED) {
                    throw new RuntimeException("AudioRecord初始化失败");
                }
                
                byte[] buffer = new byte[BUFFER_SIZE];
                audioRecord.startRecording();
                isRecording = true;
                
                Log.d(TAG, "开始语音识别");
                
                // 开始录音循环
                while (isRecording && audioRecord != null) {
                    try {
                        int readSize = audioRecord.read(buffer, 0, buffer.length);
                        if (readSize > 0) {
                            // 进行VAD检测（只在启用时）
                            if (isVadEnabled && vadDetector != null) {
                                try {
                                    // 使用缓冲区累积音频数据
                                    int remainingSpace = vadAudioBuffer.length - vadBufferPosition;
                                    int bytesToCopy = Math.min(readSize, remainingSpace);
                                    
                                    System.arraycopy(buffer, 0, vadAudioBuffer, vadBufferPosition, bytesToCopy);
                                    vadBufferPosition += bytesToCopy;
                                    
                                    // 如果缓冲区已满，进行VAD检测
                                    if (vadBufferPosition >= vadAudioBuffer.length) {
                                        //Log.d(TAG, "VAD缓冲区已满，开始VAD检测: " + vadBufferPosition + "字节");
                                        vadDetector.processAudio(vadAudioBuffer);
                                        
                                        // 重置缓冲区
                                        vadBufferPosition = 0;
                                    } else {
                                        //Log.d(TAG, "VAD缓冲区累积中: " + vadBufferPosition + "/" + vadAudioBuffer.length + "字节");
                                    }
                                } catch (Exception e) {
                                    Log.e(TAG, "VAD检测失败", e);
                                }
                            } else if (!isVadEnabled) {
                                // VAD检测被禁用时，跳过VAD处理，避免状态累积
                                // 不处理任何音频数据给VAD检测器
                            }
                            
                            // 发送音频数据到Vosk进行识别
                            if (recognizer.acceptWaveForm(buffer, readSize)) {
                                // 获取最终识别结果
                                String result = recognizer.getResult();
                                processResult(result, false);
                            } else {
                                // 获取部分识别结果
                                String partialResult = recognizer.getPartialResult();
                                processResult(partialResult, true);
                            }
                        }
                    } catch (Exception e) {
                        Log.e(TAG, "读取音频数据时发生错误", e);
                        break;
                    }
                }
                
            } catch (Exception e) {
                Log.e(TAG, "语音识别过程中发生错误", e);
                if (listener != null) {
                    mainHandler.post(() -> listener.onError("识别错误: " + e.getMessage()));
                }
            } finally {
                stopRecognition();
            }
        });
    }
    
    /**
     * 停止语音识别
     */
    public void stopRecognition() {
        Log.d(TAG, "开始停止语音识别");
        isRecording = false;
        
        if (audioRecord != null) {
            try {
                // 检查AudioRecord的状态
                if (audioRecord.getRecordingState() == AudioRecord.RECORDSTATE_RECORDING) {
                    audioRecord.stop();
                    Log.d(TAG, "AudioRecord已停止");
                }
                audioRecord.release();
                Log.d(TAG, "AudioRecord已释放");
                audioRecord = null;
            } catch (Exception e) {
                Log.e(TAG, "停止录音时发生错误", e);
                // 即使出错也要确保AudioRecord被释放
                try {
                    if (audioRecord != null) {
                        audioRecord.release();
                    }
                } catch (Exception releaseException) {
                    Log.e(TAG, "释放AudioRecord时发生错误", releaseException);
                } finally {
                    audioRecord = null;
                }
            }
        }
        
        // 不再调用getFinalResult，避免Vosk API崩溃
        Log.d(TAG, "语音识别已停止");
    }
    
    /**
     * 处理识别结果
     */
    private void processResult(String result, boolean isPartial) {
        try {
            JSONObject jsonResult = new JSONObject(result);
            String text = jsonResult.optString("text", "");
            
            if (!text.isEmpty()) {
                if (listener != null) {
                    if (isPartial) {
                        mainHandler.post(() -> listener.onPartialResult(text));
                    } else {
                        mainHandler.post(() -> listener.onResult(text));
                    }
                }
            }
        } catch (JSONException e) {
            Log.e(TAG, "解析识别结果失败", e);
        }
    }
    
    /**
     * 安全地获取最终识别结果
     * 只在需要时才调用，避免在资源释放时调用
     */
    public void getFinalResult() {
        if (recognizer != null && isModelLoaded) {
            try {
                String finalResult = recognizer.getFinalResult();
                Log.d(TAG, "获取最终结果: " + finalResult);
                processResult(finalResult, false);
            } catch (Exception e) {
                Log.e(TAG, "获取最终结果时发生错误", e);
            }
        }
    }
    
    /**
     * 释放资源
     */
    public void release() {
        Log.d(TAG, "开始释放VoskSpeechRecognizer资源");
        
        // 先停止录音
        stopRecognition();
        
        // 等待一小段时间确保录音完全停止
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        
        // 安全地关闭识别器
        if (recognizer != null) {
            try {
                // 直接关闭识别器，不调用getFinalResult避免崩溃
                recognizer.close();
                Log.d(TAG, "识别器已关闭");
            } catch (Exception e) {
                Log.e(TAG, "关闭识别器时发生错误", e);
            } finally {
                recognizer = null;
            }
        }
        
        // 安全地关闭模型
        if (model != null) {
            try {
                model.close();
                Log.d(TAG, "模型已关闭");
            } catch (Exception e) {
                Log.e(TAG, "关闭模型时发生错误", e);
            } finally {
                model = null;
            }
        }
        
        // 关闭线程池
        if (executorService != null) {
            try {
                executorService.shutdown();
                if (!executorService.awaitTermination(2, java.util.concurrent.TimeUnit.SECONDS)) {
                    executorService.shutdownNow();
                }
                Log.d(TAG, "线程池已关闭");
            } catch (Exception e) {
                Log.e(TAG, "关闭线程池时发生错误", e);
                executorService.shutdownNow();
            } finally {
                executorService = null;
            }
        }
        
        // 释放VAD检测器资源
        if (vadDetector != null) {
            try {
                vadDetector.release();
                Log.d(TAG, "VAD检测器已释放");
            } catch (Exception e) {
                Log.e(TAG, "释放VAD检测器时发生错误", e);
            } finally {
                vadDetector = null;
            }
        }
        
        // 清理主线程Handler
        if (mainHandler != null) {
            mainHandler.removeCallbacksAndMessages(null);
            mainHandler = null;
        }
        
        // 注销VAD控制广播
        if (vadControlReceiver != null) {
            androidx.localbroadcastmanager.content.LocalBroadcastManager.getInstance(context)
                .unregisterReceiver(vadControlReceiver);
            vadControlReceiver = null;
        }
        
        isModelLoaded = false;
        isRecording = false;
        isVadEnabled = false;
        
        Log.d(TAG, "VoskSpeechRecognizer资源已完全释放");
    }
    
    /**
     * 检查模型是否已加载
     */
    public boolean isModelLoaded() {
        return isModelLoaded;
    }
    
    /**
     * 检查是否正在录音
     */
    public boolean isRecording() {
        return isRecording;
    }
    
    /**
     * 设置VAD检测开关
     * @param enabled true启用VAD检测，false禁用VAD检测
     */
    public void setVadEnabled(boolean enabled) {
        this.isVadEnabled = enabled;
        Log.d(TAG, "VAD检测开关: " + (enabled ? "启用" : "禁用"));
    }
    
    /**
     * 获取VAD检测开关状态
     * @return true表示VAD检测已启用
     */
    public boolean isVadEnabled() {
        return isVadEnabled;
    }

    /**
     * 重置VAD检测器
     * 清除所有状态，避免TTS音频残留影响
     */
    public void resetVadDetector() {
        if (vadDetector != null) {
            try {
                vadDetector.reset(); // 重置VAD检测器状态
                Log.d(TAG, "🔄 VAD检测器已重置，清除TTS音频残留状态");
            } catch (Exception e) {
                Log.e(TAG, "重置VAD检测器失败", e);
            }
        }
    }

    /**
     * 暂停VAD检测
     * 在TTS播放期间调用，避免TTS音频被误识别为语音输入
     */
    public void pauseVadDetection() {
        if (vadDetector != null && isVadEnabled) {
            try {
                // 简单重置VAD状态，不清除"正在说话"状态
                // 只重置内部状态，避免TTS音频被误识别
                Log.d(TAG, "🔇 VAD检测已暂停");

                isVadEnabled = false;
                // 清空VAD缓冲区
                vadBufferPosition = 0;
                if (vadAudioBuffer != null) {
                    java.util.Arrays.fill(vadAudioBuffer, (byte)0);
                }

                if (vadDetector != null) {
                    vadDetector.reset();
                }
        Log.d(TAG, "🔇 VAD检测已暂停，缓冲区已清空");
            } catch (Exception e) {
                Log.e(TAG, "暂停VAD检测失败", e);
            }
        }
    }
    
    /**
     * 恢复VAD检测
     * TTS播放结束后调用
     */
    public void resumeVadDetection() {
        if (vadDetector != null && !isVadEnabled) {


              isVadEnabled = true;
            // 重置VAD缓冲区
            vadBufferPosition = 0;
            if (vadAudioBuffer != null) {
                java.util.Arrays.fill(vadAudioBuffer, (byte)0);
            }


            if (vadDetector != null) {
            vadDetector.reset();
        }
            Log.d(TAG, "🎤 VAD检测已恢复，缓冲区已重置");
            //Log.d(TAG, "🎤 VAD检测已恢复");
        }
    }

    /**
     * 设置音频输入源
     * @param audioSource AUDIO_SOURCE_MIC 或 AUDIO_SOURCE_DEFAULT
     */
    public void setAudioSource(int audioSource) {
        this.audioSource = audioSource;
        Log.d(TAG, "设置音频输入源: " + (audioSource == AUDIO_SOURCE_MIC ? "手机麦克风" : "默认音频源"));
    }
    
    /**
     * 获取当前音频输入源
     */
    public int getAudioSource() {
        return audioSource;
    }
    
    /**
     * 获取音频输入源名称
     */
    public String getAudioSourceName() {
        switch (audioSource) {
            case AUDIO_SOURCE_MIC:
                return "手机麦克风";
            case AUDIO_SOURCE_DEFAULT:
                return "默认音频源";
            default:
                return "未知";
        }
    }
} 